﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using Autodesk.Revit.DB;
using YJKSparseDistance.ModelLayer;
using YJKSparseDistance.Properties;
using YJKInspectModelFunc.ModelLayer;

namespace YJKSparseDistance.ControlLayer
{
	public class AreaCalculateManger
	{
		public AreaCalculateManger(AreaPacker_EvacuationDistance inputArea)
		{
			this.m_thisArea = inputArea;
			this.m_thisArea.PrePareThisArea();
			this.m_lstRunWayRooms.AddRange(this.m_thisArea.LstAllRunWayRoom);
			foreach (RoomPacker_EvacuationDistance inputValue in this.m_lstRunWayRooms)
			{
				this.m_lstRoomCurveBean.Add(new RoomCurveBean(inputValue));
			}
			for (int i = 0; i < this.m_lstRoomCurveBean.Count; i++)
			{
				this.m_lstAllWallLocationCurveBean.AddRange(this.m_lstRoomCurveBean[i].LstWallLocationCurveBean);
				for (int j = 0; j < this.m_lstRoomCurveBean.Count; j++)
				{
					if (i < j)
					{
						this.m_lstRoomCurveBean[i].SetLinkedRoom(this.m_lstRoomCurveBean[j]);
					}
				}
			}
			this.m_lstAllWallLocationCurveBean = this.m_lstAllWallLocationCurveBean.Distinct<WallLocationCurveBean>().ToList<WallLocationCurveBean>();
			List<BulidingCurvePakcer> list = new List<BulidingCurvePakcer>();
			List<BulidingCurvePakcer> list2 = new List<BulidingCurvePakcer>();
			foreach (RoomCurveBean roomCurveBean in this.m_lstRoomCurveBean)
			{
				list.AddRange(roomCurveBean.LstCurvePacker);
				list2.AddRange(roomCurveBean.LstObstructureCurvePacker);
				this.m_lstAffFreeEndPoint.AddRange(roomCurveBean.LstAllFreeEnd);
			}
			BulidingCurvePackerCompare comparer = new BulidingCurvePackerCompare();
			list = list.Distinct(comparer).ToList<BulidingCurvePakcer>();
			list2 = list2.Distinct(comparer).ToList<BulidingCurvePakcer>();
			this.m_thisWayMap = new BaseWayMapBean(list, list2, this.m_lstAllWallLocationCurveBean, this.m_lstAffFreeEndPoint);
		}

		public List<List<ResultBean>> Calculate()
		{
			List<EndPointPacker> list = new List<EndPointPacker>();
			List<EndPointPacker> list2 = new List<EndPointPacker>();
			List<BaseCurvePacker> list3 = new List<BaseCurvePacker>();
			List<Curve> list4 = new List<Curve>();
			List<XYZ> list5 = new List<XYZ>();
			List<List<ResultBean>> list6 = new List<List<ResultBean>>();
			new List<WallLocationCurveBean>();
			EndPointPacker endPointPacker = null;
			foreach (RoomCurveBean roomCurveBean in this.m_lstRoomCurveBean)
			{
				list = new List<EndPointPacker>();
				list2 = new List<EndPointPacker>();
				new List<WallLocationCurveBean>();
				list.AddRange((roomCurveBean.ThisPacker as RoomPacker_EvacuationDistance).GetAllStartPointPacker());
				list2.AddRange((roomCurveBean.ThisPacker as RoomPacker_EvacuationDistance).GetAllEndPointPacker());
				foreach (RoomCurveBean roomCurveBean2 in roomCurveBean.LstLinkRoomCurveBean)
				{
					list2.AddRange((roomCurveBean2.ThisPacker as RoomPacker_EvacuationDistance).GetAllEndPointPacker());
				}
				for (int i = 0; i < list.Count; i++)
				{
					endPointPacker = list[i];
					if (!this.IfCanContinue(endPointPacker, list2))
					{
						list6.Add(new List<ResultBean>());
						foreach (EndPointPacker endPointPacker2 in list2)
						{
							list3 = new List<BaseCurvePacker>();
							list3.AddRange(this.m_thisWayMap.GetBuildingRunWay());
							list3.AddRange(this.m_thisWayMap.SetStartPoint(endPointPacker));
							list3.AddRange(this.m_thisWayMap.SetEndPoint(endPointPacker2));
							list4 = this.GetCurves(list3);
							list4 = Utility.GetAllCurvesInOneBox(list4, endPointPacker.UseEndPoint, endPointPacker2.UseEndPoint, 4.0);
							list5 = this.m_useCalculater.CalculateShortPath(endPointPacker, endPointPacker2, list4);
							if (list5 != null)
							{
								list6[list6.Count - 1].Add(new ResultBean(endPointPacker, endPointPacker2, list5));
							}
						}
						if (list6[list6.Count - 1].Count != 0)
						{
							int useIndex = 0;
							if (endPointPacker.AppendPoint != null)
							{
								useIndex = 1;
							}
							double num = this.GetFullAngleToBasisX(list6[list6.Count - 1][0], useIndex);
							double num2 = this.GetFullAngleToBasisX(list6[list6.Count - 1][0], useIndex);
							foreach (ResultBean inputValue in list6[list6.Count - 1])
							{
								double fullAngleToBasisX = this.GetFullAngleToBasisX(inputValue, useIndex);
								if (fullAngleToBasisX < num)
								{
									num = fullAngleToBasisX;
								}
								else if (fullAngleToBasisX > num2)
								{
									num2 = fullAngleToBasisX;
								}
							}
							if (Math.PI*.5 > num2 - num)
							{
								endPointPacker.IfFinalEnd = true;
							}
						}
					}
				}
			}
			for (int j = 0; j < list6.Count; j++)
			{
				for (int k = 0; k < list6[j].Count; k++)
				{
					list6[j][k].UseRule = EvacuationDistanceArch.UesRulePacker;
				}
			}
			return list6;
		}

		private bool IfCanContinue(EndPointPacker useStartPoint, List<EndPointPacker> useEndPoints)
		{
			if (useStartPoint.UseElementPacker != null && useStartPoint.UseElementPacker is DoorPacker_EvacuationDistance)
			{
				foreach (BaseRoomPacker baseRoomPacker in (useStartPoint.UseElementPacker as DoorPacker_EvacuationDistance).LstConctRooms)
				{
					if (baseRoomPacker.ThisRoom != null && (baseRoomPacker.ThisRoom.Area < this.m_dContinueRoomArea || Regex.IsMatch(baseRoomPacker.ThisRoom.Name, Resources.Str_NoneCheckRoomName)))
					{
						return true;
					}
				}
			}
			foreach (EndPointPacker endPointPacker in useEndPoints)
			{
				if (useStartPoint.UseEndPoint.DistanceTo(endPointPacker.UseEndPoint) < this.m_dContinueDistance)
				{
					return true;
				}
			}
			return false;
		}

		public List<List<ResultBean>> CalculateAsync()
		{
			AsyncShortDistanceCalculateManger asyncShortDistanceCalculateManger = new AsyncShortDistanceCalculateManger();
			List<EndPointPacker> list = new List<EndPointPacker>();
			List<EndPointPacker> list2 = new List<EndPointPacker>();
			List<BaseCurvePacker> list3 = new List<BaseCurvePacker>();
			List<Curve> list4 = new List<Curve>();
			new List<WallLocationCurveBean>();
			List<ShortDistacneCalculateBean> list5 = new List<ShortDistacneCalculateBean>();
			foreach (RoomCurveBean roomCurveBean in this.m_lstRoomCurveBean)
			{
				list = new List<EndPointPacker>();
				list2 = new List<EndPointPacker>();
				new List<WallLocationCurveBean>();
				list.AddRange((roomCurveBean.ThisPacker as RoomPacker_EvacuationDistance).GetAllStartPointPacker());
				list2.AddRange((roomCurveBean.ThisPacker as RoomPacker_EvacuationDistance).GetAllEndPointPacker());
				foreach (RoomCurveBean roomCurveBean2 in roomCurveBean.LstLinkRoomCurveBean)
				{
					list2.AddRange((roomCurveBean2.ThisPacker as RoomPacker_EvacuationDistance).GetAllEndPointPacker());
				}
				for (int i = 0; i < list.Count; i++)
				{
					EndPointPacker endPointPacker = list[i];
					if (!this.IfCanContinue(endPointPacker, list2))
					{
						ShortDistacneCalculateBean shortDistacneCalculateBean = new ShortDistacneCalculateBean(endPointPacker);
						foreach (EndPointPacker endPointPacker2 in list2)
						{
							list3 = new List<BaseCurvePacker>();
							list3.AddRange(this.m_thisWayMap.GetBuildingRunWay());
							list3.AddRange(this.m_thisWayMap.SetStartPoint(endPointPacker));
							list3.AddRange(this.m_thisWayMap.SetEndPoint(endPointPacker2));
							list4 = this.GetCurves(list3);
							list4 = Utility.GetAllCurvesInOneBox(list4, endPointPacker.UseEndPoint, endPointPacker2.UseEndPoint, 4.0);
							shortDistacneCalculateBean.AddEndPoint(endPointPacker2, list4);
						}
						list5.Add(shortDistacneCalculateBean);
					}
				}
			}
			asyncShortDistanceCalculateManger.SetTaskes(list5);
			asyncShortDistanceCalculateManger.Do();
			return asyncShortDistanceCalculateManger.GetAllResult();
		}

		public AreaCheckResultPacker GetResult()
		{
			List<List<ResultBean>> input = this.CalculateAsync();
			return new AreaCheckResultPacker(this.m_thisArea.ThisElement as Area, input);
		}

		private double GetFullAngleToBasisX(ResultBean inputValue, int useIndex)
		{
			return Utility.GetFullAngleToBasisX(inputValue, useIndex);
		}

		private List<Curve> GetCurves(List<BaseCurvePacker> input)
		{
			new List<Curve>();
			return (from n in input
			select n.ThisCurve).ToList<Curve>();
		}

		private AreaPacker_EvacuationDistance m_thisArea;

		private BaseWayMapBean m_thisWayMap;

		private List<RoomCurveBean> m_lstRoomCurveBean = new List<RoomCurveBean>();

		private List<RoomPacker_EvacuationDistance> m_lstRunWayRooms = new List<RoomPacker_EvacuationDistance>();

		private List<WallLocationCurveBean> m_lstAllWallLocationCurveBean = new List<WallLocationCurveBean>();

		private List<XYZ> m_lstAffFreeEndPoint = new List<XYZ>();

		private ShortDistanceCalculater m_useCalculater = new ShortDistanceCalculater();

		private double m_dContinueDistance = 40.0;

		private double m_dContinueRoomArea = 54.0;
	}
}
